#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Project ：pid_control_example 
@File ：deviation_correction3.py
@IDE  ：PyCharm 
@Author ：李涵彬
@Date ：2024/5/14 下午11:30 
"""

import json
import socket
import time

# 导入简单PID库
from simple_pid import PID


# 创建一个参数配置类
class Parameters:
	def __init__(self, parameters_file: str):
		self.parameters = self.load_parameters(parameters_file)

	def load_parameters(self, parameters_file: str):
		with open(parameters_file, 'r') as file:
			return json.load(file)

	def get_parameters(self, data: dict) -> dict:
		# 从报文中获取板坯类型以及其他相关字段的值
		board_type = data["board_type"]
		other_field1 = data["other_field1"]
		other_field2 = data["other_field2"]
		# 根据板坯类型和其他字段的值选择对应的参数配置
		key = f"{board_type}_{other_field1}_{other_field2}"
		return self.parameters.get(key, self.parameters["default"])


# 解析报文获取数据
def parse_message(message: str) -> dict:
	# 解析报文，假设报文格式为 JSON
	return json.loads(message)


# 主程序
def main(parameters_file: str, host: str, port: int, second_socket_host: str, second_socket_port: int):
	# 创建参数配置对象
	parameters = Parameters(parameters_file)

	# 创建 socket 监听端口
	with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
		s.bind((host, port))
		s.listen()
		print(f"Listening on {host}:{port}...")
		conn, addr = s.accept()
		with conn:
			print(f"Connected by {addr}")
			while True:
				# 接收数据
				data = conn.recv(1024).decode("utf-8")
				if not data:
					break

				# 解析报文
				data_dict = parse_message(data)

				# 获取板坯类型和其他相关字段的值，并选择对应的参数配置
				params = parameters.get_parameters(data_dict)

				# 创建 PID 控制器对象并使用参数配置初始化
				pid = PID(params["kp"], params["ki"], params["kd"], setpoint=params["setpoint"])

				# 计算 PID 控制器的输出
				actual_value = data_dict["actual_value"]
				correction = pid(actual_value)

				# 将纠偏量数据实时传输给第二个 socket
				with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as second_socket:
					second_socket.connect((second_socket_host, second_socket_port))
					second_socket.sendall(str(correction).encode("utf-8"))

				# 模拟间隔 200ms
				time.sleep(0.2)


if __name__ == "__main__":
	# 参数文件路径
	PARAMETERS_FILE = "parameters.json"

	# 主 socket 的地址和端口
	HOST = '127.0.0.1'
	PORT = 65432

	# 第二个 socket 的地址和端口
	SECOND_SOCKET_HOST = '127.0.0.1'
	SECOND_SOCKET_PORT = 65433

	# 执行主程序
	main(PARAMETERS_FILE, HOST, PORT, SECOND_SOCKET_HOST, SECOND_SOCKET_PORT)
